package com.cby.library.tool.crash;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.cby.library.tool.crash.service.KillSelfService;
import com.cby.library.tool.crash.test.CrashTestActivity;
import com.cby.library.tool.crash.ui.CrashInfoListActivity;
import com.cby.library.tool.util.LogUtils;

import java.util.List;

/**
 * Description:CrashUtils
 *
 * @author chenbaoyang
 * @create 2020/11/20 11:14
 */
public class CrashUtils {


    /**
     * 打开奔溃信息列表页面
     *
     * @param context 上下文
     */
    public static void openCrashListPage(Context context) {
        Intent intent = new Intent(context.getApplicationContext(), CrashInfoListActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.getApplicationContext().startActivity(intent);
    }

    /**
     * 打开崩溃测试页面
     *
     * @param context 上下文
     */
    public static void openCrashTestPage(Context context) {
        Intent intent = new Intent(context.getApplicationContext(), CrashTestActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.getApplicationContext().startActivity(intent);
    }

    /**
     * 杀死进程操作，默认为异常退出
     * System.exit(0)是正常退出程序，而System.exit(1)或者说非0表示非正常退出程序
     * System.exit(1)一般放在catch块中，当捕获到异常，需要停止程序。这个status=1是用来表示这个程序是非正常退出。
     * @param isThrow                           是否是异常退出
     */
    public static void killCurrentProcess(boolean isThrow) {
        //需要杀掉原进程，否则崩溃的app处于黑屏,卡死状态
        android.os.Process.killProcess(android.os.Process.myPid());
        if (isThrow){
            System.exit(10);
        } else {
            System.exit(0);
        }
    }

    /**
     * 开启一个新的服务，用来重启本APP【使用handler延迟】
     * 软件重启，不清临时数据。
     * 重启整个APP
     * @param context                       上下文
     * @param delayed                       延迟多少毫秒
     */
    public static void restartAppWithDelay(Context context, long delayed){
        //finishActivity();
        Intent intent = new Intent(context, KillSelfService.class);
        intent.putExtra("PackageName",context.getPackageName());
        intent.putExtra("Delayed",delayed);
        context.startService(intent);
        LogUtils.i("reStartApp--- 用来重启本APP--1---");
        //exitApp();
        killCurrentProcess(true);
    }

    /**
     * 用来重启本APP[使用闹钟，整体重启，临时数据清空（推荐）]
     * 重启整个APP
     * @param context                       上下文
     * @param delayed                       延迟多少毫秒
     * @param clazz                         启动应用的目标类
     */
    public static void restartAppFromTargetActivity(Context context , long delayed, Class<?> clazz){
        Intent intent = new Intent(context.getApplicationContext(), clazz);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (intent.getComponent() != null) {
            //如果类名已经设置，我们强制它模拟启动器启动。
            //如果我们不这样做，如果你从错误活动重启，然后按home，
            //然后从启动器启动活动，主活动将在backstack上出现两次。
            //这很可能不会有任何有害的影响，因为如果你设置了Intent组件，
            //if将始终启动，而不考虑此处指定的操作。
            intent.setAction(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
        }
        PendingIntent restartIntent = PendingIntent.getActivity(
                context.getApplicationContext(), 0, intent,PendingIntent.FLAG_ONE_SHOT);
        //退出程序
        AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + delayed,restartIntent);
        LogUtils.i("reStartApp--- 用来重启本APP--2---"+clazz);
        //killCurrentProcess(true);
    }


    /**
     * 重启app
     *
     * @param context 上下文
     */
    public static void restartAppFromCurrentActivity(Context context) {
        String packageName = context.getPackageName();
        Activity activity = ActivityStackManager.getInstance().getCurrentActivity();
        Class<? extends Activity> clazz = guessRestartActivityClass(activity);
        LogUtils.i("reStartApp--- 用来重启本APP--3-"+packageName + "--"+clazz);
        Intent intent = new Intent(activity, clazz);
        restartApplicationWithIntent(activity, intent);
    }

    /**
     * 重启app，通过指定的意图（intent）
     *
     * @param activity
     * @param intent 指定的意图
     */
    private static void restartApplicationWithIntent(@NonNull Activity activity, @NonNull Intent intent) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_CLEAR_TASK |
                Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
        if (intent.getComponent() != null) {
            //如果类名已经设置，我们强制它模拟启动器启动。
            //如果我们不这样做，如果你从错误活动重启，然后按home，
            //然后从启动器启动活动，主活动将在backstack上出现两次。
            //这很可能不会有任何有害的影响，因为如果你设置了Intent组件，
            //if将始终启动，而不考虑此处指定的操作。
            intent.setAction(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
        }
        activity.startActivity(intent);
        activity.finish();
        killCurrentProcess(true);
    }


    @Nullable
    private static Class<? extends Activity> guessRestartActivityClass(@NonNull Context context) {
        Class<? extends Activity> resolvedActivityClass;
        resolvedActivityClass = getRestartActivityClassWithIntentFilter(context);
        if (resolvedActivityClass == null) {
            resolvedActivityClass = getLauncherActivity(context);
        }
        return resolvedActivityClass;
    }

    /**
     * 检索可以为给定意图执行的所有活动
     *
     * @param context
     * @return
     */
    @SuppressWarnings("unchecked")
    @Nullable
    private static Class<? extends Activity> getRestartActivityClassWithIntentFilter(@NonNull Context context) {
        Intent searchedIntent = new Intent().setPackage(context.getPackageName());
        //检索可以为给定意图执行的所有活动
        List<ResolveInfo> resolveInfo = context.getPackageManager().queryIntentActivities(searchedIntent,
                PackageManager.GET_RESOLVED_FILTER);
        if (resolveInfo.size() > 0) {
            ResolveInfo info = resolveInfo.get(0);
            try {
                return (Class<? extends Activity>) Class.forName(info.activityInfo.name);
            } catch (ClassNotFoundException e) {
                LogUtils.e(e.getMessage());
            }
        }
        return null;
    }

    /**
     * 获取当前运行的activity的class
     *
     * @param context  上下文
     * @return
     */
    @SuppressWarnings("unchecked")
    @Nullable
    private static Class<? extends Activity> getLauncherActivity(@NonNull Context context) {
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
        if (intent != null && intent.getComponent() != null) {
            try {
                return (Class<? extends Activity>) Class.forName(intent.getComponent().getClassName());
            } catch (ClassNotFoundException e) {
                LogUtils.e(e.getLocalizedMessage());
            }
        }
        return null;
    }
}
